"use strict";

const DbMixin = require("../mixins/db.mixin");

/**
 * @typedef {import('moleculer').ServiceSchema} ServiceSchema Moleculer's Service Schema
 * @typedef {import('moleculer').Context} Context Moleculer's Context
 */

/** @type {ServiceSchema} */
module.exports = {
    name: "tags",

    /**
     * Mixins
     */
    mixins: [DbMixin("tags")],

    /**
     * Settings
     */
    settings: {
        // Available fields in the responses
        fields: [
            "_id",
            "id",
            "name",
            "count",
            "showInNav",
            "sortOrder",
            "createdAt",
            "updatedAt"
        ],
        
        // Validator for the `create` & `insert` actions.
        entityValidator: {
            name: "string",
            count: "number|optional",
            showInNav: "boolean|optional",
            sortOrder: "number|optional"
        }
    },

    /**
     * Dependencies
     */
    dependencies: [],

    /**
     * Actions
     */
    actions: {
        // --- TAG MANAGEMENT ACTIONS ---
        
        /**
         * Get tags list for admin
         */
        getAdminTags: {
            rest: "GET /tags",
            cache: false,
            async handler(ctx) {
                try {
                    const { showInNav } = ctx.params;
                    
                    // 构建查询条件
                    const query = {};
                    if (showInNav !== undefined) {
                        query.showInNav = !!showInNav;
                    }
                    
                    // 获取标签数据，按sortOrder从大到小排序
                    const tags = await this.adapter.find({
                        query,
                        sort: { sortOrder: -1 }
                    });
                    
                    // 为每个标签计算关联的博客数量
                    const formattedTags = await Promise.all(tags.map(async (tag) => {
                        // 计算使用该标签的博客数量 - tags是数组，需要使用$in查询
                        const blogCount = await ctx.call("blog.count", {
                            query: { tags: { $in: [tag._id.toString()] } }
                        });
                        
                        return {
                            id: tag._id.toString(),
                            name: tag.name,
                            count: blogCount || 0,
                            showInNav: tag.showInNav !== undefined ? tag.showInNav : false,
                            sortOrder: tag.sortOrder || 0,
                            createdAt: tag.createdAt ? tag.createdAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN'),
                            updatedAt: tag.updatedAt ? tag.updatedAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN')
                        };
                    }));
                    
                    return {
                        code: 200,
                        data: formattedTags,
                        message: "success"
                    };
                } catch (error) {
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Get hot tags
         */
        getHotTags: {
            rest: "GET /tags/hot",
            cache: false,
            async handler(ctx) {
                try {
                    // 获取所有标签
                    const tags = await this.adapter.find({});
                    
                    // 为每个标签计算关联的博客数量
                    const tagsWithCount = await Promise.all(tags.map(async (tag) => {
                        const blogCount = await ctx.call("blog.count", {
                            query: { tags: { $in: [tag._id.toString()] } }
                        });
                        
                        return {
                            id: tag._id.toString(),
                            name: tag.name,
                            count: blogCount || 0
                        };
                    }));
                    
                    // 按 count 降序排序，取前5个
                    const formattedTags = tagsWithCount
                        .sort((a, b) => b.count - a.count)
                        .slice(0, 5);
                    
                    return {
                        code: 200,
                        data: formattedTags,
                        message: "success"
                    };
                } catch (error) {
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Add a new tag
         */
        addTag: {
            rest: "POST /tags",
            cache: false,
            params: {
                name: "string",
                showInNav: "boolean|optional",
                sortOrder: "number|optional"
            },
            async handler(ctx) {
                const { name, showInNav = false, sortOrder = 0 } = ctx.params;
                
                try {
                    // Check if the tag name already exists
                    const existingTag = await this.adapter.findOne({ name: name });
                    if (existingTag) {
                        return {
                            code: 400,
                            data: null,
                            message: "标签名称已存在"
                        };
                    }
                    
                    // Create a new tag in the database
                    const newTag = await this.adapter.insert({
                        name: name,
                        count: 0,
                        showInNav: showInNav,
                        sortOrder: sortOrder,
                        createdAt: new Date(),
                        updatedAt: new Date()
                    });
                    
                    // Format the response data
                    const formattedTag = {
                        id: newTag._id.toString(),
                        name: newTag.name,
                        count: newTag.count || 0,
                        showInNav: newTag.showInNav,
                        sortOrder: newTag.sortOrder,
                        createdAt: newTag.createdAt.toLocaleString('zh-CN'),
                        updatedAt: newTag.updatedAt.toLocaleString('zh-CN')
                    };
                    
                    return {
                        code: 200,
                        data: formattedTag,
                        message: "添加成功"
                    };
                } catch (error) {
                    if (error.message === "标签名称已存在") {
                        return {
                            code: 400,
                            data: null,
                            message: "标签名称已存在"
                        };
                    }
                    
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Update a tag
         */
        updateTag: {
            rest: "PUT /tags/:id",
            cache: false,
            params: {
                id: "string",
                name: "string|optional",
                showInNav: "boolean|optional",
                sortOrder: "number|optional"
            },
            async handler(ctx) {
                const { id } = ctx.params;
                const { name, showInNav, sortOrder } = ctx.params;
                
                try {
                    // Check if the tag exists
                    const existingTag = await this.adapter.findById(id);
                    if (!existingTag) {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    // 准备更新数据
                    const updateData = {
                        updatedAt: new Date()
                    };
                    
                    // 如果提供了名称，且名称发生了变化，检查是否重复并更新
                    if (name !== undefined && name !== existingTag.name) {
                        // Check if the new name already exists for another tag
                        const duplicateTag = await this.adapter.findOne({ name: name });
                        if (duplicateTag) {
                            return {
                                code: 400,
                                data: null,
                                message: "标签名称已存在"
                            };
                        }
                        updateData.name = name;
                    } else if (name !== undefined) {
                        // 名称没有变化，但仍然需要在updateData中设置（保持原值）
                        updateData.name = name;
                    }
                    
                    // 更新显示状态和排序字段（如果提供）
                    if (showInNav !== undefined) {
                        updateData.showInNav = showInNav;
                    }
                    
                    if (sortOrder !== undefined) {
                        updateData.sortOrder = sortOrder;
                    }
                    
                    // Update the tag in the database
                    const updatedTag = await this.adapter.updateById(id, {
                        $set: updateData
                    });
                    
                    // Format the response data
                    const formattedTag = {
                        id: updatedTag._id.toString(),
                        name: updatedTag.name,
                        count: updatedTag.count || 0,
                        showInNav: updatedTag.showInNav !== undefined ? updatedTag.showInNav : false,
                        sortOrder: updatedTag.sortOrder || 0,
                        createdAt: updatedTag.createdAt.toLocaleString('zh-CN'),
                        updatedAt: updatedTag.updatedAt.toLocaleString('zh-CN')
                    };
                    
                    return {
                        code: 200,
                        data: formattedTag,
                        message: "更新成功"
                    };
                } catch (error) {
                    if (error.message === "标签不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    if (error.message === "标签名称已存在") {
                        return {
                            code: 400,
                            data: null,
                            message: "标签名称已存在"
                        };
                    }
                    
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Delete a tag
         */
        deleteTag: {
            rest: "DELETE /tags/:id",
            cache: false,
            params: {
                id: "string"
            },
            async handler(ctx) {
                const { id } = ctx.params;
                
                try {
                    // Check if tag exists
                    const tag = await this.adapter.findById(id);
                    if (!tag) {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    // In a real implementation, you would check if the tag is used by any articles
                    // This would involve querying the articles collection
                    
                    // For now, we'll just delete the tag
                    await this.adapter.removeById(id);
                    
                    return {
                        code: 200,
                        data: null,
                        message: "删除成功"
                    };
                } catch (error) {
                    if (error.message === "标签不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    if (error.message === "该标签下有文章，无法删除") {
                        return {
                            code: 400,
                            data: null,
                            message: "该标签下有文章，无法删除"
                        };
                    }
                    
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Batch delete tags
         */
        batchDeleteTags: {
            rest: "DELETE /tags/batch",
            cache: false,
            params: {
                ids: "array"
            },
            async handler(ctx) {
                const { ids } = ctx.params;
                
                try {
                    // Check if any tags don't exist
                    const tags = await this.adapter.find({ _id: { $in: ids } });
                    const foundIds = tags.map(tag => tag._id.toString());
                    const nonExistingIds = ids.filter(id => !foundIds.includes(id));
                    
                    if (nonExistingIds.length > 0) {
                        return {
                            code: 404,
                            data: null,
                            message: `标签ID ${nonExistingIds.join(', ')} 不存在`
                        };
                    }
                    
                    // In a real implementation, you would check if any tags are used by articles
                    // This would involve querying the articles collection
                    
                    // For now, we'll just delete the tags
                    await this.adapter.removeMany({ _id: { $in: ids } });
                    
                    return {
                        code: 200,
                        data: null,
                        message: "删除成功"
                    };
                } catch (error) {
                    if (error.message.includes("不存在")) {
                        return {
                            code: 404,
                            data: null,
                            message: error.message
                        };
                    }
                    
                    if (error.message.includes("无法删除")) {
                        return {
                            code: 400,
                            data: null,
                            message: error.message
                        };
                    }
                    
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },
        
        /**
         * Check tag usage
         */
        checkTagUsage: {
            rest: "GET /tags/:id/usage",
            cache: false,
            params: {
                id: "string"
            },
            async handler(ctx) {
                const { id } = ctx.params;
                
                try {
                    // Check if tag exists
                    const tag = await this.adapter.findById(id);
                    if (!tag) {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    // In a real implementation, you would query the database to check usage
                    // This would involve querying the articles collection for articles with this tag ID
                    // For now, we'll just return basic usage data based on the tag's count field
                    
                    const usageData = {
                        articleCount: tag.count || 0,
                        isUsed: (tag.count || 0) > 0
                    };
                    
                    return {
                        code: 200,
                        data: usageData,
                        message: "success"
                    };
                } catch (error) {
                    if (error.message === "标签不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "标签不存在"
                        };
                    }
                    
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        }
    },

    /**
     * Methods
     */
    methods: {},

    /**
     * Events
     */
    events: {},

    /**
     * Service created lifecycle event handler
     */
    created() {},

    /**
     * Service started lifecycle event handler
     */
    async started() {
        // Seed some mock data if needed
    },

    /**
     * Service stopped lifecycle event handler
     */
    async stopped() {}
};